Set up

suppressPackageStartupMessages({
  library(tidyverse)
})

Directories and File Inputs/Outputs

# Detect the ".git" folder -- this will be in the project root directory
# Use this as the root directory to ensure proper sourcing of functions 
# no matter where this is called from
root_dir <- rprojroot::find_root(rprojroot::has_dir(".git"))
analysis_dir <- file.path(root_dir, "analyses", "tmb-vaf-longitudinal")
results_dir <- file.path(analysis_dir, "results")
input_dir <- file.path(analysis_dir, "input")
files_dir <- file.path(root_dir, "analyses", "sample-distribution-analysis", "results")

# Input files
pbta_file <- file.path(files_dir, "pbta.tsv") # file from add-sample-distribution module
genomic_paired_file <- file.path(files_dir, "genomic_assays_matched_time_points.tsv")
tmb_vaf_file <- file.path(results_dir, "tmb_vaf_genomic.tsv")
palette_file <- file.path(root_dir, "figures", "palettes", "oncoprint_color_palette.tsv")

# File path to plot directory
plots_dir <-
  file.path(analysis_dir, "plots")
if (!dir.exists(plots_dir)) {
  dir.create(plots_dir)
}

source(paste0(root_dir, "/figures/scripts/theme.R"))
source(paste0(analysis_dir, "/util/function-create-barplot.R"))

Read in data and process

pbta_df <- readr::read_tsv(pbta_file, guess_max = 100000, show_col_types = FALSE) %>% 
  select(Kids_First_Participant_ID, Kids_First_Biospecimen_ID, cg_multiple, cg_id, cgGFAC, tumor_descriptor)

tmb_vaf_df <- readr::read_tsv(tmb_vaf_file, guess_max = 100000, show_col_types = FALSE) %>% 
  filter(!tmb >= 10) %>% 
  select(Kids_First_Biospecimen_ID, Variant_Classification, gene_protein, mutation_count,   region_size, tmb, VAF)

genomic_paired_df <- readr::read_tsv(genomic_paired_file, guess_max = 100000, show_col_types = FALSE) %>%
  left_join(pbta_df, by = c("Kids_First_Participant_ID")) %>% 
  left_join(tmb_vaf_df, by = c("Kids_First_Biospecimen_ID")) %>%
  filter(!is.na(tmb))

# Attention as some bs specimen might not have TMB!
# If that happens, we will end up with samples lacking timepoints.

# Which patient samples don't have TMB?
# genomic_paired_df %>% 
#  filter(is.na(tmb)) %>% 
#  unique() %>% 
#  regulartable() %>%
#  fontsize(size = 12, part = "all")

descriptors_df <- genomic_paired_df %>%
  group_by(Kids_First_Participant_ID) %>%
  summarize(descriptors = paste(sort(tumor_descriptor), collapse = ", "),) 

# Vector to order timepoints
timepoints <- c("Diagnosis", "Progressive", "Recurrence", "Deceased", "Second Malignancy", "Unavailable")

df <- genomic_paired_df %>% 
  left_join(descriptors_df, by = c("Kids_First_Participant_ID", "descriptors")) %>% 
  mutate(td_cgGFAC = case_when(grepl("Deceased", tumor_descriptor) ~ "xDeceased",
                               TRUE ~ tumor_descriptor),
         log10_tmb = abs(log10(tmb)),
         cg_id_kids = paste(cg_id, Kids_First_Participant_ID, sep = "_"),
         cg_id_kids = str_replace(cg_id_kids, "/", "_"),
         cg_id_kids = str_replace(cg_id_kids, "-", "_"),
         cg_id_kids = str_replace_all(cg_id_kids, " ", "_"))

# Let's count #samples per cancer groups and timepoints.
# We will use the cg_id col that indicates cancer type as identified at the first diagnostic sample
timepoint_cg_n_df <- df %>% 
  count(cg_id, tumor_descriptor) %>% 
  dplyr::mutate(timepoint_cg_n = glue::glue("{cg_id}_{tumor_descriptor}  (N={n})")) %>% 
  dplyr::rename(timepoint_cg_number = n) 

# Let's count number of samples per cancer groups and timepoints 
timepoint_cgGFAC_n_df <- df %>% 
  count(cgGFAC, td_cgGFAC) %>% 
  dplyr::mutate(timepoint_cgGFAC_n = glue::glue("{cgGFAC}_{td_cgGFAC}  (N={n})")) %>% 
  dplyr::rename(timepoint_cgGFAC_number = n) 

# Create df to use for plots
df_plot <- df %>% 
  left_join(timepoint_cg_n_df, by = c("tumor_descriptor", "cg_id")) %>%
  left_join(timepoint_cgGFAC_n_df, by = c("td_cgGFAC", "cgGFAC")) %>% 
  filter(!timepoint_cg_n <= 2,
         !timepoint_cgGFAC_n <= 2,
         !cg_id == "NA") %>% 
  mutate(tumor_descriptor = factor(tumor_descriptor),
         tumor_descriptor = fct_relevel(tumor_descriptor, timepoints))
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `tumor_descriptor = fct_relevel(tumor_descriptor, timepoints)`.
Caused by warning:
! 1 unknown level in `f`: Unavailable
# Let's count number of samples 
count_df <- df_plot %>% 
  group_by(tumor_descriptor, cg_id, Kids_First_Biospecimen_ID, Variant_Classification) %>% 
  dplyr::count(cg_id) 

#count_df <- df_plot %>% 
#  dplyr::count(cg_id) %>% 
#  mutate(pct = n / sum(n) * 100)

Define parameters for plots

# Read color palette
palette_df <- readr::read_tsv(palette_file, guess_max = 100000, show_col_types = FALSE) 

# Define and order palette
palette <- palette_df$hex_codes
names(palette) <- palette_df$color_names

Alterations per timepoint

# Define parameters for function
x_value <- count_df$tumor_descriptor
title <- paste("Variant types in PBTA cohort", sep = " ")

# Run function
fname <- paste0(plots_dir, "/", "Alteration_type_timepoints_barplots.pdf")
print(fname)
[1] "/Users/chronia/CHOP/GitHub/pbta-tumor-evolution/analyses/tmb-vaf-longitudinal/plots/Alteration_type_timepoints_barplots.pdf"
p <- create_stacked_barplot_variant(count_df = count_df, x = x_value, palette = palette, title = title)
pdf(file = fname, width = 6, height = 6)
print(p)
dev.off()
quartz_off_screen 
                2 

Alterations per timepoint in each cancer type

cg_id_id <- as.character(unique(count_df$cg_id)) 
cg_id_id <- sort(cg_id_id, decreasing = FALSE)
cg_id_id
 [1] "Adamantinomatous Craniopharyngioma"       "Atypical Teratoid Rhabdoid Tumor"         "Chordoma"                                
 [4] "Choroid plexus carcinoma"                 "CNS Embryonal tumor"                      "Craniopharyngioma"                       
 [7] "Diffuse midline glioma"                   "Dysembryoplastic neuroepithelial tumor"   "Embryonal tumor with multilayer rosettes"
[10] "Ependymoma"                               "Ewing sarcoma"                            "Ganglioglioma"                           
[13] "Glial-neuronal tumor"                     "Hemangioblastoma"                         "High-grade glioma"                       
[16] "Low-grade glioma"                         "Malignant peripheral nerve sheath tumor"  "Medulloblastoma"                         
[19] "Meningioma"                               "Neuroblastoma"                            "Neurofibroma/Plexiform"                  
[22] "Pilocytic astrocytoma"                    "Rosai-Dorfman disease"                    "Schwannoma"                              
# Define parameters for function
x_value <- count_df$Kids_First_Biospecimen_ID
title <- paste("Variant types in PBTA cohort across cancer groups", sep = " ")

# Run function
p <- create_stacked_barplot_variant_cg_id(count_df = count_df, x = x_value, palette = palette, title = title)

Alterations per timepoint in each cancer type defined by cgGFAC

df_plot_cgGFAC <- df_plot %>%
  filter(!is.na(timepoints_models)) %>% 
  arrange(timepoint_cgGFAC_n) %>% 
  group_by(tumor_descriptor, cgGFAC, timepoint_cgGFAC_n, Kids_First_Biospecimen_ID, Variant_Classification) %>% 
  dplyr::count(timepoint_cgGFAC_n)

cgGFAC_id <- as.character(unique(df_plot_cgGFAC$cgGFAC)) 
cgGFAC_id <- sort(cgGFAC_id, decreasing = FALSE)
cgGFAC_id
[1] "ATRT"  "DMG"   "HGG"   "LGG"   "Other"
# Define parameters for function
x_value <- df_plot_cgGFAC$Kids_First_Biospecimen_ID
title <- paste("Variant types in PBTA cohort across cgGFAC", sep = " ")

# Run function
p <- create_stacked_barplot_variant_cgGFAC(count_df = df_plot_cgGFAC, x = x_value, palette = palette, title = title)

Alterations per timepoint in each cancer type and timepoint model

tm_df_plot <- df_plot %>%
  filter(!is.na(timepoints_models)) %>% 
  group_by(tumor_descriptor, cg_id, timepoints_models, Kids_First_Biospecimen_ID, Variant_Classification) %>% 
  dplyr::count(timepoint_cgGFAC_n)

tm <- as.character(unique(tm_df_plot$timepoints_models))
tm <- sort(tm, decreasing = FALSE)
tm
 [1] "Dx-Dec"         "Dx-Pro"         "Dx-Pro-Dec"     "Dx-Pro-Rec"     "Dx-Pro-Rec-Dec" "Dx-Rec"         "Dx-Rec-Dec"     "Dx-SM"         
 [9] "Pro-Dec"        "Pro-Rec"        "Pro-Rec-Dec"    "Rec-Dec"        "Rec-SM"        
# Loop through variable
for (i in seq_along(tm)){
  print(i)
  df_sub <- tm_df_plot %>%
      filter(timepoints_models == tm[i])
  
   # Define parameters for function
  x_value <- df_sub$Kids_First_Biospecimen_ID
  title <- paste(tm[i])
  
  # Run function
  p <- create_stacked_barplot_variant_cg_id(count_df = df_sub, x = x_value, palette = palette, title = title)
  
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13

sessionInfo()
R version 4.2.3 (2023-03-15)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.5.2

Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] ggthemes_4.2.4  lubridate_1.9.2 forcats_1.0.0   stringr_1.5.0   dplyr_1.1.2     purrr_1.0.1     readr_2.1.4     tidyr_1.3.0    
 [9] tibble_3.2.1    ggplot2_3.4.2   tidyverse_2.0.0

loaded via a namespace (and not attached):
 [1] tidyselect_1.2.0  xfun_0.39         bslib_0.5.0       carData_3.0-5     colorspace_2.1-0  vctrs_0.6.3       generics_0.1.3   
 [8] htmltools_0.5.5   yaml_2.3.7        utf8_1.2.3        rlang_1.1.1       pillar_1.9.0      jquerylib_0.1.4   ggpubr_0.6.0     
[15] glue_1.6.2        withr_2.5.0       bit64_4.0.5       lifecycle_1.0.3   munsell_0.5.0     ggsignif_0.6.4    gtable_0.3.3     
[22] ragg_1.2.5        evaluate_0.21     labeling_0.4.2    knitr_1.43        tzdb_0.4.0        fastmap_1.1.1     parallel_4.2.3   
[29] fansi_1.0.4       broom_1.0.5       scales_1.2.1      backports_1.4.1   cachem_1.0.8      vroom_1.6.3       jsonlite_1.8.7   
[36] abind_1.4-5       systemfonts_1.0.4 farver_2.1.1      bit_4.0.5         textshaping_0.3.6 hms_1.1.3         digest_0.6.33    
[43] stringi_1.7.12    rstatix_0.7.2     rprojroot_2.0.3   cli_3.6.1         tools_4.2.3       magrittr_2.0.3    sass_0.4.7       
[50] crayon_1.5.2      car_3.1-2         pkgconfig_2.0.3   timechange_0.2.0  rmarkdown_2.23    rstudioapi_0.15.0 R6_2.5.1         
[57] compiler_4.2.3   
LS0tCnRpdGxlOiAiQ2xhc3NpZmljYXRpb24gb2YgVmFyaWFudHMgYWNyb3NzIHBhaXJlZCBsb25naXR1ZGluYWwgc2FtcGxlcyBpbiB0aGUgUEJUQSBDb2hvcnQiCmF1dGhvcjogJ0FudG9uaWEgQ2hyb25pIDxjaHJvbmlhQGNob3AuZWR1PiBmb3IgRDNCJwpkYXRlOiAiMjAyMyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IFRSVUUKICAgIHRvY19mbG9hdDogVFJVRQotLS0KCiMgU2V0IHVwCmBgYHtyIGxvYWQtbGlicmFyeX0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKICBsaWJyYXJ5KHRpZHl2ZXJzZSkKfSkKYGBgCgojIERpcmVjdG9yaWVzIGFuZCBGaWxlIElucHV0cy9PdXRwdXRzCmBgYHtyIHNldC1kaXItYW5kLWZpbGUtbmFtZXN9CiMgRGV0ZWN0IHRoZSAiLmdpdCIgZm9sZGVyIC0tIHRoaXMgd2lsbCBiZSBpbiB0aGUgcHJvamVjdCByb290IGRpcmVjdG9yeQojIFVzZSB0aGlzIGFzIHRoZSByb290IGRpcmVjdG9yeSB0byBlbnN1cmUgcHJvcGVyIHNvdXJjaW5nIG9mIGZ1bmN0aW9ucyAKIyBubyBtYXR0ZXIgd2hlcmUgdGhpcyBpcyBjYWxsZWQgZnJvbQpyb290X2RpciA8LSBycHJvanJvb3Q6OmZpbmRfcm9vdChycHJvanJvb3Q6Omhhc19kaXIoIi5naXQiKSkKYW5hbHlzaXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInRtYi12YWYtbG9uZ2l0dWRpbmFsIikKcmVzdWx0c19kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgInJlc3VsdHMiKQppbnB1dF9kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgImlucHV0IikKZmlsZXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInNhbXBsZS1kaXN0cmlidXRpb24tYW5hbHlzaXMiLCAicmVzdWx0cyIpCgojIElucHV0IGZpbGVzCnBidGFfZmlsZSA8LSBmaWxlLnBhdGgoZmlsZXNfZGlyLCAicGJ0YS50c3YiKSAjIGZpbGUgZnJvbSBhZGQtc2FtcGxlLWRpc3RyaWJ1dGlvbiBtb2R1bGUKZ2Vub21pY19wYWlyZWRfZmlsZSA8LSBmaWxlLnBhdGgoZmlsZXNfZGlyLCAiZ2Vub21pY19hc3NheXNfbWF0Y2hlZF90aW1lX3BvaW50cy50c3YiKQp0bWJfdmFmX2ZpbGUgPC0gZmlsZS5wYXRoKHJlc3VsdHNfZGlyLCAidG1iX3ZhZl9nZW5vbWljLnRzdiIpCnBhbGV0dGVfZmlsZSA8LSBmaWxlLnBhdGgocm9vdF9kaXIsICJmaWd1cmVzIiwgInBhbGV0dGVzIiwgIm9uY29wcmludF9jb2xvcl9wYWxldHRlLnRzdiIpCgojIEZpbGUgcGF0aCB0byBwbG90IGRpcmVjdG9yeQpwbG90c19kaXIgPC0KICBmaWxlLnBhdGgoYW5hbHlzaXNfZGlyLCAicGxvdHMiKQppZiAoIWRpci5leGlzdHMocGxvdHNfZGlyKSkgewogIGRpci5jcmVhdGUocGxvdHNfZGlyKQp9Cgpzb3VyY2UocGFzdGUwKHJvb3RfZGlyLCAiL2ZpZ3VyZXMvc2NyaXB0cy90aGVtZS5SIikpCnNvdXJjZShwYXN0ZTAoYW5hbHlzaXNfZGlyLCAiL3V0aWwvZnVuY3Rpb24tY3JlYXRlLWJhcnBsb3QuUiIpKQpgYGAKCiMgUmVhZCBpbiBkYXRhIGFuZCBwcm9jZXNzCgpgYGB7ciBsb2FkLXByb2Nlc3MtaW5wdXRzfQpwYnRhX2RmIDwtIHJlYWRyOjpyZWFkX3RzdihwYnRhX2ZpbGUsIGd1ZXNzX21heCA9IDEwMDAwMCwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lIAogIHNlbGVjdChLaWRzX0ZpcnN0X1BhcnRpY2lwYW50X0lELCBLaWRzX0ZpcnN0X0Jpb3NwZWNpbWVuX0lELCBjZ19tdWx0aXBsZSwgY2dfaWQsIGNnR0ZBQywgdHVtb3JfZGVzY3JpcHRvcikKCnRtYl92YWZfZGYgPC0gcmVhZHI6OnJlYWRfdHN2KHRtYl92YWZfZmlsZSwgZ3Vlc3NfbWF4ID0gMTAwMDAwLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUgCiAgZmlsdGVyKCF0bWIgPj0gMTApICU+JSAKICBzZWxlY3QoS2lkc19GaXJzdF9CaW9zcGVjaW1lbl9JRCwgVmFyaWFudF9DbGFzc2lmaWNhdGlvbiwgZ2VuZV9wcm90ZWluLCBtdXRhdGlvbl9jb3VudCwJcmVnaW9uX3NpemUsIHRtYiwgVkFGKQoKZ2Vub21pY19wYWlyZWRfZGYgPC0gcmVhZHI6OnJlYWRfdHN2KGdlbm9taWNfcGFpcmVkX2ZpbGUsIGd1ZXNzX21heCA9IDEwMDAwMCwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiAgbGVmdF9qb2luKHBidGFfZGYsIGJ5ID0gYygiS2lkc19GaXJzdF9QYXJ0aWNpcGFudF9JRCIpKSAlPiUgCiAgbGVmdF9qb2luKHRtYl92YWZfZGYsIGJ5ID0gYygiS2lkc19GaXJzdF9CaW9zcGVjaW1lbl9JRCIpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHRtYikpCgojIEF0dGVudGlvbiBhcyBzb21lIGJzIHNwZWNpbWVuIG1pZ2h0IG5vdCBoYXZlIFRNQiEKIyBJZiB0aGF0IGhhcHBlbnMsIHdlIHdpbGwgZW5kIHVwIHdpdGggc2FtcGxlcyBsYWNraW5nIHRpbWVwb2ludHMuCgojIFdoaWNoIHBhdGllbnQgc2FtcGxlcyBkb24ndCBoYXZlIFRNQj8KIyBnZW5vbWljX3BhaXJlZF9kZiAlPiUgCiMgIGZpbHRlcihpcy5uYSh0bWIpKSAlPiUgCiMgIHVuaXF1ZSgpICU+JSAKIyAgcmVndWxhcnRhYmxlKCkgJT4lCiMgIGZvbnRzaXplKHNpemUgPSAxMiwgcGFydCA9ICJhbGwiKQoKZGVzY3JpcHRvcnNfZGYgPC0gZ2Vub21pY19wYWlyZWRfZGYgJT4lCiAgZ3JvdXBfYnkoS2lkc19GaXJzdF9QYXJ0aWNpcGFudF9JRCkgJT4lCiAgc3VtbWFyaXplKGRlc2NyaXB0b3JzID0gcGFzdGUoc29ydCh0dW1vcl9kZXNjcmlwdG9yKSwgY29sbGFwc2UgPSAiLCAiKSwpIAoKIyBWZWN0b3IgdG8gb3JkZXIgdGltZXBvaW50cwp0aW1lcG9pbnRzIDwtIGMoIkRpYWdub3NpcyIsICJQcm9ncmVzc2l2ZSIsICJSZWN1cnJlbmNlIiwgIkRlY2Vhc2VkIiwgIlNlY29uZCBNYWxpZ25hbmN5IiwgIlVuYXZhaWxhYmxlIikKCiMgQ3JlYXRlIGRmIHRvIHVzZSBmb3IgcGxvdHMKZGZfcGxvdCA8LSBnZW5vbWljX3BhaXJlZF9kZiAlPiUgCiAgbGVmdF9qb2luKGRlc2NyaXB0b3JzX2RmLCBieSA9IGMoIktpZHNfRmlyc3RfUGFydGljaXBhbnRfSUQiLCAiZGVzY3JpcHRvcnMiKSkgJT4lIAogIG11dGF0ZSh0ZF9jZ0dGQUMgPSBjYXNlX3doZW4oZ3JlcGwoIkRlY2Vhc2VkIiwgdHVtb3JfZGVzY3JpcHRvcikgfiAieERlY2Vhc2VkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiB0dW1vcl9kZXNjcmlwdG9yKSwKICAgICAgICAgbG9nMTBfdG1iID0gYWJzKGxvZzEwKHRtYikpLAogICAgICAgICBjZ19pZF9raWRzID0gcGFzdGUoY2dfaWQsIEtpZHNfRmlyc3RfUGFydGljaXBhbnRfSUQsIHNlcCA9ICJfIiksCiAgICAgICAgIGNnX2lkX2tpZHMgPSBzdHJfcmVwbGFjZShjZ19pZF9raWRzLCAiLyIsICJfIiksCiAgICAgICAgIGNnX2lkX2tpZHMgPSBzdHJfcmVwbGFjZShjZ19pZF9raWRzLCAiLSIsICJfIiksCiAgICAgICAgIGNnX2lkX2tpZHMgPSBzdHJfcmVwbGFjZV9hbGwoY2dfaWRfa2lkcywgIiAiLCAiXyIpLAogICAgICAgICB0dW1vcl9kZXNjcmlwdG9yID0gZmFjdG9yKHR1bW9yX2Rlc2NyaXB0b3IpLAogICAgICAgICB0dW1vcl9kZXNjcmlwdG9yID0gZmN0X3JlbGV2ZWwodHVtb3JfZGVzY3JpcHRvciwgdGltZXBvaW50cykpCgojIExldCdzIGNvdW50IG51bWJlciBvZiBzYW1wbGVzIApjb3VudF9kZiA8LSBkZl9wbG90ICU+JSAKICBncm91cF9ieSh0dW1vcl9kZXNjcmlwdG9yLCBjZ19pZCwgS2lkc19GaXJzdF9CaW9zcGVjaW1lbl9JRCwgVmFyaWFudF9DbGFzc2lmaWNhdGlvbikgJT4lIAogIGRwbHlyOjpjb3VudChjZ19pZCkgCgpgYGAgCgojIERlZmluZSBwYXJhbWV0ZXJzIGZvciBwbG90cwoKYGBge3IgZGVmaW5lLXBhcmFtZXRlcnMtZm9yLXBsb3RzfQojIFJlYWQgY29sb3IgcGFsZXR0ZQpwYWxldHRlX2RmIDwtIHJlYWRyOjpyZWFkX3RzdihwYWxldHRlX2ZpbGUsIGd1ZXNzX21heCA9IDEwMDAwMCwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgCgojIERlZmluZSBhbmQgb3JkZXIgcGFsZXR0ZQpwYWxldHRlIDwtIHBhbGV0dGVfZGYkaGV4X2NvZGVzCm5hbWVzKHBhbGV0dGUpIDwtIHBhbGV0dGVfZGYkY29sb3JfbmFtZXMKCmBgYAoKIyBBbHRlcmF0aW9ucyBwZXIgdGltZXBvaW50CgpgYGB7ciBwbG90LXRpbWVwb2ludCwgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDYsIGZpZy5mdWxsd2lkdGggPSBUUlVFfQojIERlZmluZSBwYXJhbWV0ZXJzIGZvciBmdW5jdGlvbgp4X3ZhbHVlIDwtIGNvdW50X2RmJHR1bW9yX2Rlc2NyaXB0b3IKdGl0bGUgPC0gcGFzdGUoIlZhcmlhbnQgdHlwZXMgaW4gUEJUQSBjb2hvcnQiLCBzZXAgPSAiICIpCgojIFJ1biBmdW5jdGlvbgpmbmFtZSA8LSBwYXN0ZTAocGxvdHNfZGlyLCAiLyIsICJBbHRlcmF0aW9uX3R5cGVfdGltZXBvaW50c19iYXJwbG90cy5wZGYiKQpwcmludChmbmFtZSkKcCA8LSBjcmVhdGVfc3RhY2tlZF9iYXJwbG90X3ZhcmlhbnQoY291bnRfZGYgPSBjb3VudF9kZiwgeCA9IHhfdmFsdWUsIHBhbGV0dGUgPSBwYWxldHRlLCB0aXRsZSA9IHRpdGxlKQpwZGYoZmlsZSA9IGZuYW1lLCB3aWR0aCA9IDYsIGhlaWdodCA9IDYpCnByaW50KHApCmRldi5vZmYoKQpgYGAKCiMgQWx0ZXJhdGlvbnMgcGVyIHRpbWVwb2ludCBpbiBlYWNoIGNhbmNlciB0eXBlCgpgYGB7ciBwbG90LWNnLWlkLCBmaWcud2lkdGggPSAzMCwgZmlnLmhlaWdodCA9IDE4LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KY2dfaWRfaWQgPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShjb3VudF9kZiRjZ19pZCkpIApjZ19pZF9pZCA8LSBzb3J0KGNnX2lkX2lkLCBkZWNyZWFzaW5nID0gRkFMU0UpCmNnX2lkX2lkCgojIERlZmluZSBwYXJhbWV0ZXJzIGZvciBmdW5jdGlvbgp4X3ZhbHVlIDwtIGNvdW50X2RmJEtpZHNfRmlyc3RfQmlvc3BlY2ltZW5fSUQKdGl0bGUgPC0gcGFzdGUoIlZhcmlhbnQgdHlwZXMgaW4gUEJUQSBjb2hvcnQgYWNyb3NzIGNhbmNlciBncm91cHMiLCBzZXAgPSAiICIpCgojIFJ1biBmdW5jdGlvbgpwIDwtIGNyZWF0ZV9zdGFja2VkX2JhcnBsb3RfdmFyaWFudF9jZ19pZChjb3VudF9kZiA9IGNvdW50X2RmLCB4ID0geF92YWx1ZSwgcGFsZXR0ZSA9IHBhbGV0dGUsIHRpdGxlID0gdGl0bGUpCgpgYGAKCiMgQWx0ZXJhdGlvbnMgcGVyIHRpbWVwb2ludCBpbiBlYWNoIGNhbmNlciB0eXBlIGRlZmluZWQgYnkgY2dHRkFDCgpgYGB7ciBwbG90LWNnR0ZBQy1uLWluZGl2aWR1YWwtcGxvdHMsIGZpZy53aWR0aCA9IDUsIGZpZy5oZWlnaHQgPSA1LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KZGZfcGxvdF9jZ0dGQUMgPC0gZGZfcGxvdCAlPiUKICBmaWx0ZXIoIWlzLm5hKHRpbWVwb2ludHNfbW9kZWxzKSkgJT4lIAogIGFycmFuZ2UodGltZXBvaW50X2NnR0ZBQ19uKSAlPiUgCiAgZ3JvdXBfYnkodHVtb3JfZGVzY3JpcHRvciwgY2dHRkFDLCB0aW1lcG9pbnRfY2dHRkFDX24sIEtpZHNfRmlyc3RfQmlvc3BlY2ltZW5fSUQsIFZhcmlhbnRfQ2xhc3NpZmljYXRpb24pICU+JSAKICBkcGx5cjo6Y291bnQodGltZXBvaW50X2NnR0ZBQ19uKQoKY2dHRkFDX2lkIDwtIGFzLmNoYXJhY3Rlcih1bmlxdWUoZGZfcGxvdF9jZ0dGQUMkY2dHRkFDKSkgCmNnR0ZBQ19pZCA8LSBzb3J0KGNnR0ZBQ19pZCwgZGVjcmVhc2luZyA9IEZBTFNFKQpjZ0dGQUNfaWQKCiMgRGVmaW5lIHBhcmFtZXRlcnMgZm9yIGZ1bmN0aW9uCnhfdmFsdWUgPC0gZGZfcGxvdF9jZ0dGQUMkS2lkc19GaXJzdF9CaW9zcGVjaW1lbl9JRAp0aXRsZSA8LSBwYXN0ZSgiVmFyaWFudCB0eXBlcyBpbiBQQlRBIGNvaG9ydCBhY3Jvc3MgY2dHRkFDIiwgc2VwID0gIiAiKQoKIyBSdW4gZnVuY3Rpb24KcCA8LSBjcmVhdGVfc3RhY2tlZF9iYXJwbG90X3ZhcmlhbnRfY2dHRkFDKGNvdW50X2RmID0gZGZfcGxvdF9jZ0dGQUMsIHggPSB4X3ZhbHVlLCBwYWxldHRlID0gcGFsZXR0ZSwgdGl0bGUgPSB0aXRsZSkKCmBgYAoKIyBBbHRlcmF0aW9ucyBwZXIgdGltZXBvaW50IGluIGVhY2ggY2FuY2VyIHR5cGUgYW5kIHRpbWVwb2ludCBtb2RlbAoKYGBge3IgcGxvdC10aW1lcG9pbnQtbW9kZWwsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gMTIsIGZpZy5mdWxsd2lkdGggPSBUUlVFfQp0bV9kZl9wbG90IDwtIGRmX3Bsb3QgJT4lCiAgZmlsdGVyKCFpcy5uYSh0aW1lcG9pbnRzX21vZGVscykpICU+JSAKICBncm91cF9ieSh0dW1vcl9kZXNjcmlwdG9yLCBjZ19pZCwgdGltZXBvaW50c19tb2RlbHMsIEtpZHNfRmlyc3RfQmlvc3BlY2ltZW5fSUQsIFZhcmlhbnRfQ2xhc3NpZmljYXRpb24pICU+JSAKICBkcGx5cjo6Y291bnQodGltZXBvaW50X2NnR0ZBQ19uKQoKdG0gPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZSh0bV9kZl9wbG90JHRpbWVwb2ludHNfbW9kZWxzKSkKdG0gPC0gc29ydCh0bSwgZGVjcmVhc2luZyA9IEZBTFNFKQp0bQoKIyBMb29wIHRocm91Z2ggdmFyaWFibGUKZm9yIChpIGluIHNlcV9hbG9uZyh0bSkpewogIHByaW50KGkpCiAgZGZfc3ViIDwtIHRtX2RmX3Bsb3QgJT4lCiAgICAgIGZpbHRlcih0aW1lcG9pbnRzX21vZGVscyA9PSB0bVtpXSkKICAKICAgIyBEZWZpbmUgcGFyYW1ldGVycyBmb3IgZnVuY3Rpb24KICB4X3ZhbHVlIDwtIGRmX3N1YiRLaWRzX0ZpcnN0X0Jpb3NwZWNpbWVuX0lECiAgdGl0bGUgPC0gcGFzdGUodG1baV0pCiAgCiAgIyBSdW4gZnVuY3Rpb24KICBwIDwtIGNyZWF0ZV9zdGFja2VkX2JhcnBsb3RfdmFyaWFudF9jZ19pZChjb3VudF9kZiA9IGRmX3N1YiwgeCA9IHhfdmFsdWUsIHBhbGV0dGUgPSBwYWxldHRlLCB0aXRsZSA9IHRpdGxlKQogIAp9CmBgYAoKCmBgYHtyIGVjaG89VFJVRX0Kc2Vzc2lvbkluZm8oKQpgYGAK